package org.walkframework.sample.business.sample.app;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.walkframework.boot.ehdb.annotation.WalkTransactional;
import org.walkframework.boot.ehdb.bean.PageResult;
import org.walkframework.boot.ehdb.bean.Pagination;
import org.walkframework.boot.ehdb.dao.StaticDAO;
import org.walkframework.boot.util.AssertUtil;
import org.walkframework.boot.util.BeanUtils;
import org.walkframework.boot.util.DateUtil;
import org.walkframework.sample.business.sample.adapter.web.request.SamplePageQueryRequest;
import org.walkframework.sample.business.sample.infra.dataobject.Sample;

import java.util.List;
import java.util.Map;

/**
 * 简易业务测试服务实现
 *
 * @author 尾生
 * @since 2024/4/9
 */
@Service
public class SimpleCrudService {

    // 给普通查询对象的查询SQL
    private static final String PAGE_BY_SQL = "select * from WALK_SAMPLE where IS_DELETED = 0 AND ID = :id? (AND NAME LIKE concat('%', :name, '%'))?";
    // 给DO对象的查询SQL
    private static final String PAGE_BY_SQL_FOR_DO = "select * from WALK_SAMPLE where IS_DELETED = 0 AND ID = :ID? (AND NAME LIKE concat('%', :NAME, '%'))?";

    /**
     * 装配默认的数据源操作对象，其他数据源，使用数据源名称+StaticDAO如orderStaticDAO变量名即可
     */
    @Autowired
    private StaticDAO baseStaticDAO;

    // 测试事务管理
    @WalkTransactional
    public Long insert(Sample sample) {
        sample.letIsDeleted(false).letCreator("admin").letCreateTime(DateUtil.now());
        baseStaticDAO.save(sample);
        if (StringUtils.equals(sample.getName(), "testTransaction")) {
            throw new RuntimeException("testTransaction");
        }
        return sample.getId();
    }

    public Sample get(Long id) {
        return baseStaticDAO.queryOne(new Sample().letId(id));
    }

    public boolean update(Sample sample) {
        AssertUtil.notNull(sample.getId(), "id不能为空");
        // 由于识别更新需要使用set方法，所以需要使用BeanUtils.copyFieldsWithSetMethod拷贝到新对象
        Sample sample1 = BeanUtils.transferWithSetMethodSimple(sample, Sample.class);
        return baseStaticDAO.updateById(sample1);
    }

    public boolean delete(Long id) {
        AssertUtil.notNull(id, "id不能为空");
        return baseStaticDAO.deleteById(new Sample().letId(id));
    }

    public List<Sample> list(Sample sample) {
        // 设置查询字段，不查询页面不使用的字段
        sample.queryBuilder().id().name().finishBuilder();
        // 为保护系统，默认只查询回2000条，可通过设置参数来调整，见EhDbConfig.defaultMaxPageSize
        return baseStaticDAO.queryBeans(sample);
    }

    public PageResult<Sample> page(SamplePageQueryRequest sample) {
        Pagination pagination = sample.toPagination();
        Sample query = new Sample().letIsDeleted(false); // 只查询未删除数据
        if (null != sample.getId()) {
            // 精确查询，每次set都认为是等值查询，所以如果不需要空字段需要事先判断，如果设置为null，则可能什么也查询不到，因为通常数据库认的是is null
            query.setId(sample.getId());
        }
        if (StringUtils.isNotEmpty(sample.getName())) {
            // 模糊查询
            query.andOperators().name(Sample.Columns.NAME).like(sample.getName());
        }
        // 排序需要放到最后设置，因为目前渲染是按顺序渲染的
        sample.decorateOrderBys(query);
        return baseStaticDAO.queryByPage(query, pagination);
    }


    public PageResult<Sample> pageBySqlForDO(SamplePageQueryRequest sample) {
        // 如果是系统生成的DO对象，参数名全大写，如果是普通对象，参数名同字段名
        Sample query = BeanUtils.transferWithSetMethodSimple(sample, Sample.class);
        return baseStaticDAO.queryByPageWithSql(PAGE_BY_SQL_FOR_DO, query, sample.toPagination());
        // 方法2，不需要转Bean参数此时使用字段名的SQL
        // return baseStaticDAO.queryByPageWithSql(PAGE_BY_SQL, sample, sample.toPagination(), Sample.class);
    }

    public PageResult<Map<String, Object>> pageBySql(SamplePageQueryRequest sample) {
        // 普通对象，参数名同字段名
        return baseStaticDAO.queryMapByPageWithSql(PAGE_BY_SQL, sample, sample.toPagination());
    }
}
